PTA数据结构题目集 第七周——图(中)

发表于 2020-08-08 1507 字 8 min read

文章目录
cos's avatar

cos

FE / ACG / 手工 / 深色模式强迫症 / INFP / 兴趣广泛养两只猫的老宅女 / remote

暂无目录
剑指offer day31 数学(困难)剑指offer day30 分治算法(困难)剑指offer day29 动态规划(困难)剑指offer day28 搜索与回溯算法(困难)剑指offer day27 栈与队列(困难)剑指offer day26 字符串(中等)剑指offer day25 模拟(中等)剑指offer day24 数学(中等)剑指offer day23 数学(简单)剑指offer day22 位运算(中等)剑指offer day21 位运算(简单)剑指offer day20 分治算法(中等)剑指offer day19 搜索与回溯算法(中等)剑指offer day18 搜索与回溯算法(中等)剑指offer day17 排序(中等)剑指offer day16 排序(简单)剑指offer day15 搜索与回溯算法(中等)剑指offer day14 搜索与回溯算法(中等)剑指offer day13 双指针(简单)剑指offer day12 双指针(简单)剑指offer day11 双指针(简单)剑指offer day10 动态规划(中等)剑指offer day9 动态规划(中等)剑指offer day8 动态规划(简单)剑指offer day7 搜索与回溯算法(简单)剑指offer day6 搜索与回溯算法(简单)剑指offer day5 查找算法(中等)剑指offer day4 查找算法(简单)剑指offer day3 字符串(简单)剑指offer day2 链表(简单)剑指offer day1 栈与队列(简单)冲刺春招-精选笔面试66题大通关day22冲刺春招-精选笔面试66题大通关day21冲刺春招-精选笔面试66题大通关day20冲刺春招-精选笔面试66题大通关day19冲刺春招-精选笔面试66题大通关18冲刺春招-精选笔面试66题大通关17冲刺春招-精选笔面试66题大通关16冲刺春招-精选笔面试66题大通关day15冲刺春招-精选笔面试66题大通关day14冲刺春招-精选笔面试66题大通关day13冲刺春招-精选笔面试66题大通关day12冲刺春招-精选笔面试66题大通关day11冲刺春招-精选笔面试66题大通关day10冲刺春招-精选笔面试66题大通关day9冲刺春招-精选笔面试66题大通关day8冲刺春招-精选笔面试66题大通关day7冲刺春招-精选笔面试66题大通关day6冲刺春招-精选笔面试66题大通关day5冲刺春招-精选笔面试66题大通关day4冲刺春招-精选笔面试66题大通关day3冲刺春招-精选笔面试66题大通关day2冲刺春招-精选笔面试66题大通关day12021秋PAT乙级真题题解及赛后总结PAT乙级刷题感想及踩坑总结PTA数据结构题目集 第三周——栽树(二叉树等)PTA数据结构题目集 第十一周——散列查找PTA数据结构题目集 第十周——排序(下)PTA数据结构题目集 第九周——排序(上)PTA数据结构题目集 第八周——图(下)PTA数据结构题目集 第七周——图(中)PTA数据结构题目集 第六周——图(上)PTA数据结构题目集 第五周——堆&哈夫曼树&并查集PTA数据结构题目集 第四周——二叉搜索树&二叉平衡树PTA数据结构题目集 第二周——线性结构PTA数据结构题目集 第一周——最大子列和算法、二分查找MOOC浙大数据结构课后题记录——PTA数据结构题目集(全)2020蓝桥杯省模拟赛题目记录

题目集总目录 学习指路博客 图论

07-图 4 哈利·波特的考试 (25 分)

本题链接

是很基本的算法应用,一定要做。如果不会,那么看看小白专场,会详细介绍 C 语言的实现方法

题目大意

给出每两个动物之间所需魔咒长度 哈利·波特最后应该带去考场的动物要使得最难变的动物所需总魔咒长度最小。 输出哈利·波特最后应该带去考场的动物的编号、以及最长的变形魔咒的长度

思路

用 Floyd 算法得出最短路矩阵 dist(dist[i][j]表示 i 到 j 所需最短长度,在每行里找最难变(即 dist[i][j]最大)的元素,在这些元素中找最小的,输出最小值的下标 i 和最小值

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 1005;
const int inf  = 0x3f3f3f;
int N,M,x,y,z;
bool visited[maxn];
int dist[maxn][maxn];
//用Floyd算法得到最短路矩阵
//让最难变的动物咒语长度最小
void init() {
    for(int i = 1; i <= N; ++i) {
       for(int j = 1; j <= N; ++j) {
            dist[i][j] = inf;
        }
        dist[i][i] = 0;
    }
}
void Floyd() {
    for(int k = 1; k <= N; ++k) {
        for(int i = 1; i <= N; ++i) {
            for(int j = 1; j <= N; ++j) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
}
void solve() {
    int num,ans,hardest;
    ans = inf+1;
    Floyd();
    for(int i = 1; i <= N; ++i) {
        hardest = 0;
        for(int j = 1; j <= N; ++j) {
            if(dist[i][j] > hardest) {
                hardest = dist[i][j];
            }
        }
        if(hardest == inf) {
            printf("0");
            return;
        }
        if(hardest < ans) {
            num = i;
            ans = hardest;
        }
    }
    printf("%d %d\n", num, ans);
}
int main(){
    scanf("%d %d", &N, &M);
    init();
    for(int i = 1; i <= M; ++i) {
        scanf("%d %d %d", &x, &y, &z);
        dist[x][y] = dist[y][x] = z;
    }
    solve();
    return 0;
}

测试点

测试点如下 在这里插入图片描述

07-图 5 Saving James Bond - Hard Version (30 分)

本题链接

有余力的话,好人做到底,如果上周已经尝试着救过 007 了,这周就继续给他建议吧;

题目大意

输出最少的跳转次数以及沿途跳转的鳄鱼的 xy 坐标

思路

用 Floyd 算法得出最短路矩阵 edge(edge[i][j]表示鳄鱼 i 到鳄鱼 j 所需最少跳转次数,初始化时能跳转则置为 1,不能则置为 0),同时用 path 存储路径。 注意一点:如果有许多最短路径,只需输出具有最小第一跳转的路径

代码

// 07-图5 Saving James Bond - Hard Version (30分)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 105;
const int inf = 0x3f3f3f;
int N,D;
bool vis[maxn];
int edge[maxn][maxn];
int path[maxn][maxn];
struct Point {
    int x, y;
    bool visited;
} v[maxn],s;
struct Fjump{
    int id;
    double d;
    bool operator<(const Fjump& f) {
        return d < f.d;
    }
};
vector<Fjump> fj;
void init() {
    for(int i = 0; i <= N+1; ++i) {
        for(int j = 0; j <= N+1; ++j) {
            edge[i][j] = inf;
            path[i][j] = -1;
        }
        edge[i][i] = 0;
    }
}
double countDist(Point a, Point b) {
    return sqrt(pow((a.x-b.x),2) + pow((a.y-b.y),2));
}
bool check(Point a) {
    int s = 50 - D;
    if(abs(a.x) >= s || abs(a.y) >= s)
        return true;
    else return false;
}
void Floyd() {
    for(int k = 1; k <= N; ++k) {
        for(int i = 1; i <= N; ++i) {
            for(int j = 1; j <= N; ++j) {
                if(edge[i][k] + edge[k][j] < edge[i][j]) {
                    edge[i][j] = edge[i][k] + edge[k][j];
                    path[i][j] = k;
                }
            }
        }
    }
}
bool firstJump(int i) {
    double d = countDist(s,v[i]);
    d -= 7.5;
    return d <= D;
}
void PrintPath(int S, int E) {
    if(path[S][E] != -1) {
        int k = path[S][E];
        PrintPath(S,k);
        printf("%d %d\n", v[k].x, v[k].y);
        PrintPath(k,E);
    }
}
int main(){
    ios::sync_with_stdio(false);
    scanf("%d %d", &N, &D);
    init();
    v[0].visited = false;
    v[0].x = v[0].y = 0;
    for(int i = 1; i <= N; ++i) {
        scanf("%d %d", &v[i].x, &v[i].y);
        v[i].visited = false;
    }
    for(int i = 1; i <= N; ++i) {
        for(int j = 1; j <= N; ++j) {
            if(countDist(v[i],v[j]) <= D)
                edge[i][j] = edge[j][i] = 1;
        }
    }
    Floyd();
    int mind,temp;
    int S,E;
    mind = inf;
    for(int i = 1; i <= N; ++i) {
        if(firstJump(i)) {
            Fjump f;
            f.d = countDist(s, v[i]);
            f.id = i;
            fj.push_back(f);
        }
    }
    sort(fj.begin(), fj.end());
    for(int i = 0; i < fj.size(); ++i) {
        int sa = fj[i].id;
        if(check(v[sa])) {
                S = sa;
                E = sa;
                mind = 2;
                break;
         }
        for(int j = 1; j <= N; ++j) {
            if(sa == j) continue;
            if(check(v[j])) {
                temp = 2 + edge[sa][j];
                if (temp < mind) {
                    S = sa;
                    E = j;
                    mind = temp;
                }
            }
        }
    }
    if(D >= 42.5) { //一步上岸
        printf("1\n");
    } else if (mind != inf) {
        printf("%d\n", mind);
        if(S == E) {
            printf("%d %d\n", v[S].x, v[S].y);
        } else {
            printf("%d %d\n", v[S].x, v[S].y);
            PrintPath(S,E);
            printf("%d %d\n", v[E].x, v[E].y);
        }
    }  else
        printf("0\n");
    return 0;
}

测试点

测试点如下 在这里插入图片描述

07-图 6 旅游规划 (25 分)

本题链接

Dijkstra 算法的变形——姥姥只能帮你到这里了,自己动脑筋想一下怎么改造经典去解决这个问题?实在不会也不要急,再下周会讲算法的。

题目大意

给你所有村庄之间的高速公路距离及其所需花费,计算并输出给定的两村庄之间所需最小距离及其花费,若有多条最小路径则输出花费最少的。

思路

Dijkstra 算法的变形,只需存边的时候同时存储距离及花费,多加一个 cost 数组,更新 dist 时的同时更新 cost。

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 505;
const int inf  = 0x3f3f3f;
int N,M,S,D,u,v,len,p;
struct Edge {
    int len, pay;
}e[maxn][maxn];
int dist[maxn];
int cost[maxn];
bool vis[maxn];
void init() {
    for(int i = 0; i <= N; ++i) {
        for(int j = 0; j <= N; ++j) {
            e[i][j].pay = e[i][j].len = inf;
        }
        e[i][i].pay = e[i][i].len = 0;
    }
    memset(vis, 0, sizeof(vis));
}
void Dijstra(int u) {
    for(int i = 0; i < N; ++i) {
        dist[i] = e[u][i].len;
        cost[i] = e[u][i].pay;
    }
    for(int i = 1; i <= N; ++i) {
        int t, mindis = inf;
        for(int j = 0; j < N; ++j) {
            if(!vis[j] && dist[j] <= mindis) {
                mindis = dist[j];
                t = j;
            }
        }
        vis[t] = true;
        for(int j = 0; j < N; ++j) {
            if(vis[j] || e[t][j].len == inf) continue;
            if(dist[j] > e[t][j].len + dist[t]) {
                dist[j] = e[t][j].len + dist[t];
                cost[j] = e[t][j].pay + cost[t];
            } else if(dist[j] == e[t][j].len + dist[t]) {
                if(cost[j] > e[t][j].pay + cost[t]) {
                    cost[j] = e[t][j].pay + cost[t];
                }
            }
        }
    }
}
int main(){
    scanf("%d %d %d %d", &N, &M, &S, &D);
    init();
    while(M--) {
        scanf("%d %d %d %d", &u, &v, &len, &p);
        e[u][v].len = e[v][u].len = len;
        e[u][v].pay = e[v][u].pay = p;
    }
    Dijstra(S);
    printf("%d %d\n", dist[D], cost[D]);
    return 0;
}

测试点

测试点如下 在这里插入图片描述

先使用 Remark42 作为临时评论系统,样式等有待优化

409k
35:31
184
使用字体寒蝉全圆体 · 感谢 字图 CDN 提供中文字体公益服务
© 2020 - 2025 cos @cosine
Powered by theme astro-koharu · Inspired by Shoka